package com.divillysausages.dsair.throttle 
{
	import com.divillysausages.dsair.DSAir;
	import flash.desktop.NativeApplication;
	import flash.events.Event;
	
	/**
	 * The ThrottleManager listens for the active and inactive events for the app and
	 * toggles the framerate accordingly
	 * @author Damian Connolly
	 */
	public class ThrottleManager 
	{
		
		/********************************************************************/
		
		private static var m_instance:ThrottleManager	= null;	// the only instance of the throttle manager
		private static var m_creating:Boolean			= false;// are we creating the throttle manager?
		
		/********************************************************************/
		
		/**
		 * The singleton instance for the throttle manager
		 */
		public static function get instance():ThrottleManager
		{
			if ( ThrottleManager.m_instance == null )
			{
				ThrottleManager.m_creating = true;
				ThrottleManager.m_instance = new ThrottleManager;
				ThrottleManager.m_creating = false;
			}
			return ThrottleManager.m_instance;
		}
		
		/********************************************************************/
		
		private var m_active:Boolean	= false;// are we active (should we throttle?)
		private var m_defaultFPS:int	= 0;	// the app default fps
		private var m_inactiveFPS:int	= 5;	// the app inactive fps
		private var m_onChange:Function	= null; // the function to call if the app's activity changes
		
		/********************************************************************/
		
		/**
		 * Is the ThrottleManager active?
		 */
		public function get active():Boolean { return this.m_active; }
		public function set active( b:Boolean ):void
		{
			if ( b )
				this._activate();
			else
				this._deactivate();
		}
		
		/**
		 * Is the app currently active?
		 */
		public function get isAppActive():Boolean { return DSAir.stage.frameRate == this.m_defaultFPS; }

		/**
		 * The current framerate of the app
		 */
		public function get framerate():int { return DSAir.stage.frameRate; }
		public function set framerate( i:int ):void
		{
			i = ( i < 0 ) ? 0 : i;
			DSAir.log( this, "Setting the application's fps to " + i + "fps" );
			DSAir.stage.frameRate 	= i;
			this.m_defaultFPS		= i;
		}
		
		/**
		 * The active fps of the app. Changing this will change the stage frame
		 * rate only if we're currently active
		 */
		public function get activeFPS():int { return this.m_defaultFPS; }
		public function set activeFPS( i:int ):void
		{
			// are we currently at this fps?
			var isCurrent:Boolean 	= ( this.framerate == this.m_defaultFPS );
			this.m_defaultFPS 		= ( i < 0 ) ? 0 : i;
			if ( isCurrent )
				DSAir.stage.frameRate = this.m_defaultFPS;
			DSAir.log( this, "Setting the application's active fps to " + this.m_defaultFPS + "fps" );
		}
		
		/**
		 * The inactive fps of the app
		 */
		public function get inactiveFPS():int { return this.m_inactiveFPS; }
		public function set inactiveFPS( i:int ):void
		{
			this.m_inactiveFPS = ( i < 0 ) ? 0 : i;
			DSAir.log( this, "Setting the application's inactive fps to " + this.m_inactiveFPS + "fps" );
		}
		
		/**
		 * The callback to call when the app's activity level changes. It should take no parameters
		 */
		public function set onAppActiveChange( f:Function ):void
		{
			if ( f != null && f.length != 0 )
			{
				DSAir.error( this, "The onAppActiveChange callback takes no parameters" );
				return;
			}
			this.m_onChange = f;
		}
		
		/********************************************************************/
		
		/**
		 * Creates a ThrottleManager. As ThrottleManager is a singleton, this shouldn't be called
		 * directly, but rather the static instance getter instead
		 */
		public function ThrottleManager() 
		{
			if ( !ThrottleManager.m_creating )
				throw new Error( "ThrottleManager is a singleton. Use the static instance getter instead" );
				
			// get the default fps
			this.m_defaultFPS = DSAir.stage.frameRate;
		}
		
		/********************************************************************/
		
		// called when we want to activate throttling
		private function _activate():void
		{
			this.m_active = true;
			NativeApplication.nativeApplication.addEventListener( Event.ACTIVATE, this._onAppActivate ); 
			NativeApplication.nativeApplication.addEventListener( Event.DEACTIVATE, this._onAppDeactivate );
		}
		
		// called when we want to deactivate throttling
		private function _deactivate():void
		{
			this.m_active = false;
			NativeApplication.nativeApplication.removeEventListener( Event.ACTIVATE, this._onAppActivate ); 
			NativeApplication.nativeApplication.removeEventListener( Event.DEACTIVATE, this._onAppDeactivate );
		}
		
		// called when the app is activated (focused)
		private function _onAppActivate( e:Event ):void
		{
			DSAir.log( this, "App activated, setting the framerate to the default " + this.m_defaultFPS + "fps" );
			DSAir.stage.frameRate = this.m_defaultFPS;
			
			// call our callback
			if ( this.m_onChange != null )
				this.m_onChange();
		}
		
		// called when the app is deactivated (unfocused)
		private function _onAppDeactivate( e:Event ):void
		{
			DSAir.log( this, "App deactivated, setting the framerate to the base " + this.m_inactiveFPS + "fps" );
			DSAir.stage.frameRate = this.m_inactiveFPS;
			
			// call our callback
			if ( this.m_onChange != null )
				this.m_onChange();
		}
		
	}

}